#ifndef CODE_GEN_HXX
#define CODE_GEN_HXX

#include "rutil/Data.hxx"
#include "rutil/Time.hxx"
#include <iostream>

namespace codegen
{
    class GenConfig
    {
    public:
        typedef enum GenType { AUTO, JSON, XML } GenType;

        static GenConfig& instance() {
            static GenConfig config;
            return config;
        }

        void set(const resip::Data& base_class_name = resip::Data::Empty,
            GenType type = AUTO,
            const resip::Data& out_file_ext = ".h",
            bool use_file_value = false,
            bool enable_indent = true, bool reserve_tab = false, unsigned int space_count = 4);

        const resip::Data& get_base_class_name() const { return base_class_name_; }
        const GenType& get_type() const { return type_; }
        const resip::Data& get_out_file_ext() const { return out_file_ext_; }
        const bool& get_use_file_value() const { return use_file_value_; }
        const bool& get_enable_indent() const { return enable_indent_; }
        const bool& get_reserve_tab() const { return reserve_tab_; }
        unsigned int get_space_count() const { return space_count_; }
    private:
        GenConfig();
        ~GenConfig() {}

        // base class name for inheritance
        resip::Data base_class_name_;
        GenType type_;
        // generate out file extension
        resip::Data out_file_ext_;
        // use value in file to assign member value as default value when construct object.
        //   otherwise, use 0 value corresponding to the member type
        bool use_file_value_;
        // indent parameters
        bool enable_indent_;
        bool reserve_tab_;
        unsigned int space_count_;
    };

    class PathInfo
    {
    public:
        PathInfo(const resip::Data& filepath);
        GenConfig::GenType get_type() const;
        static GenConfig::GenType get_type(const resip::Data& ext);

        resip::Data path_;
        resip::Data name_;
        resip::Data class_name_;
        resip::Data ext_full_;
        resip::Data ext_;
    };

    class CodeGen
    {
    public:
        CodeGen(const resip::Data& path) : path_(path) {}

        void generate();

    protected:
        bool _generate(const resip::Data& in_filepath);

        bool _generate_json(const resip::Data& in_filepath);
        bool _generate_xml(const resip::Data& in_filepath);
        bool _generate_auto(const resip::Data& in_filepath);

    private:
        resip::Data path_;
    };
}

#endif // #ifndef CODE_GEN_HXX

